#include <iostream>
#include "OperationMode_CFB.hpp"

OperationMode_CFB::OperationMode_CFB(Algorithm &system, unsigned int j) : OperationMode(system), j(j) {
	R = Block(system.getBlockSize(), 0xff);
}

OperationMode_CFB::OperationMode_CFB(Algorithm &system, const Block &iv, unsigned char j) : OperationMode(system), j(j), R(iv) {
	
}

Block OperationMode_CFB::encrypt(const Block &plaintext) {
	
	//encrypt register
	Block encrypted = system.encrypt(R);
	//extract first j bits
	Block firstPart = Block(encrypted.get(), j / 8);
	
	//XOR with Plaintext
	Block ciphertext = plaintext;
	ciphertext ^= firstPart;
	
	//shift register
	R <<= j;
	//and append the ciphertext
	unsigned char* array = R.get();
	memcpy(array + 16 -(j / 8), ciphertext.get(), j / 8);
	//finally store the result in the register again
	R = Block(array, 16);
	
	return ciphertext;
}

Block OperationMode_CFB::decrypt(const Block &ciphertext) {
	
	//encrypt register
	Block decrypted = system.encrypt(R);
	//extract first j bits
	Block firstPart = Block(decrypted.get(), j / 8);
	
	//XOR with Plaintext
	Block plaintext = ciphertext;
	plaintext ^= firstPart;
	
	//shift register
	R <<= j;
	//and append the ciphertext
	unsigned char* array = R.get();
	memcpy(array + 16 -(j / 8), ciphertext.get(), j / 8);
	//finally store the result in the register again
	R = Block(array, 16);

	return plaintext;
}
